// Test Runner for Tool Manager

import * as path from 'path';
import * as fs from 'fs';
import { ToolManager } from '../core/tool-manager';
import { ToolCategory } from '../core/interfaces';

/**
 * 简单的测试框架
 */
class TestFramework {
    private tests: Array<{ name: string; fn: () => Promise<void> }> = [];
    private passed = 0;
    private failed = 0;

    test(name: string, fn: () => Promise<void>) {
        this.tests.push({ name, fn });
    }

    async run(): Promise<void> {
        console.log(`\n🧪 Running ${this.tests.length} tests...\n`);

        for (const test of this.tests) {
            try {
                await test.fn();
                console.log(`✅ ${test.name}`);
                this.passed++;
            } catch (error) {
                console.log(`❌ ${test.name}`);
                console.log(`   Error: ${error instanceof Error ? error.message : `${error}`}`);
                this.failed++;
            }
        }

        console.log(`\n📊 Test Results:`);
        console.log(`   Passed: ${this.passed}`);
        console.log(`   Failed: ${this.failed}`);
        console.log(`   Total: ${this.tests.length}`);

        if (this.failed > 0) {
            process.exit(1);
        }
    }
}

/**
 * 断言函数
 */
function assert(condition: boolean, message: string) {
    if (!condition) {
        throw new Error(message);
    }
}

function assertEqual(actual: any, expected: any, message?: string) {
    if (actual !== expected) {
        throw new Error(message || `Expected ${expected}, but got ${actual}`);
    }
}

function assertNotNull(value: any, message?: string) {
    if (value === null || value === undefined) {
        throw new Error(message || 'Expected value to not be null or undefined');
    }
}

/**
 * 主测试函数
 */
async function runTests() {
    const testFramework = new TestFramework();
    const toolManager = new ToolManager();

    // 测试工具管理器初始化
    testFramework.test('ToolManager initialization', async () => {
        await toolManager.initialize();
        assert(toolManager.getAvailableTools().length > 0, 'Should have registered tools');
    });

    // 测试文件操作工具
    testFramework.test('File operations - read-file tool availability', async () => {
        const isAvailable = toolManager.isToolAvailable('read-file');
        assert(isAvailable, 'read-file tool should be available');
    });

    testFramework.test('File operations - save-file tool availability', async () => {
        const isAvailable = toolManager.isToolAvailable('save-file');
        assert(isAvailable, 'save-file tool should be available');
    });

    testFramework.test('File operations - str-replace-editor tool availability', async () => {
        const isAvailable = toolManager.isToolAvailable('str-replace-editor');
        assert(isAvailable, 'str-replace-editor tool should be available');
    });

    // 测试进程管理工具
    testFramework.test('Process management - launch-process tool availability', async () => {
        const isAvailable = toolManager.isToolAvailable('launch-process');
        assert(isAvailable, 'launch-process tool should be available');
    });

    testFramework.test('Process management - kill-process tool availability', async () => {
        const isAvailable = toolManager.isToolAvailable('kill-process');
        assert(isAvailable, 'kill-process tool should be available');
    });

    // 测试工具分类
    testFramework.test('Tool categorization', async () => {
        const fileTools = toolManager.getToolsByCategory(ToolCategory.FILE_OPERATIONS);
        const processTools = toolManager.getToolsByCategory(ToolCategory.PROCESS_MANAGEMENT);

        assert(fileTools.length >= 3, 'Should have at least 3 file operation tools');
        assert(processTools.length >= 5, 'Should have at least 5 process management tools');
    });

    // 测试文件读写功能
    testFramework.test('File operations - save and read file', async () => {
        const testFilePath = path.join(__dirname, 'test-file.txt');
        const testContent = 'Hello, World!\nThis is a test file.';

        const context = {
            workspaceRoot: process.cwd(),
            environment: process.env as Record<string, string>,
            timestamp: new Date(),
            permissions: ['file:read', 'file:write']
        };

        try {
            // 保存文件
            const saveResult = await toolManager.executeTool('save-file', {
                path: testFilePath,
                content: testContent
            }, context);

            assert(saveResult.success, 'Save file should succeed');

            // 读取文件
            const readResult = await toolManager.executeTool('read-file', {
                path: testFilePath
            }, context);

            assert(readResult.success, 'Read file should succeed');
            assertNotNull(readResult.data, 'Should have data');
            assertNotNull(readResult.data.data, 'Should have nested data');
            assertNotNull(readResult.data.data.content, 'Should have content');
            assertEqual(readResult.data.data.content.trim(), testContent, 'File content should match');

        } finally {
            // 清理测试文件
            try {
                await fs.promises.unlink(testFilePath);
            } catch (error) {
                // 忽略清理错误
            }
        }
    });

    // 测试进程执行
    testFramework.test('Process management - simple command execution', async () => {
        const context = {
            workspaceRoot: process.cwd(),
            environment: process.env as Record<string, string>,
            timestamp: new Date(),
            permissions: ['process:execute', 'process:read', 'process:write', 'process:kill']
        };

        const result = await toolManager.executeTool('launch-process', {
            command: 'echo "Hello from process"',
            wait: true,
            max_wait_seconds: 10,
            cwd: process.cwd()
        }, context);

        assert(result.success, 'Process execution should succeed');
        assertNotNull(result.data, 'Should have data');
        assertNotNull(result.data.data, 'Should have nested data');
        assertNotNull(result.data.data.terminal_id, 'Should return terminal ID');
        assert(result.data.data.completed, 'Process should be completed');
    });

    // 测试工具统计
    testFramework.test('Tool statistics', async () => {
        const stats = toolManager.getToolStats();

        assertNotNull(stats.totalTools, 'Should have total tools count');
        assertNotNull(stats.enabledTools, 'Should have enabled tools count');
        assertNotNull(stats.categories, 'Should have categories breakdown');

        assert(stats.totalTools > 0, 'Should have registered tools');
        assert(stats.enabledTools > 0, 'Should have enabled tools');
    });

    // 测试错误处理
    testFramework.test('Error handling - invalid tool name', async () => {
        const result = await toolManager.executeTool('non-existent-tool', {});
        assert(!result.success, 'Should fail for non-existent tool');
        assert(result.error !== undefined, 'Should have error information');
        assert(result.error!.message.includes('not found'), 'Should indicate tool not found');
    });

    testFramework.test('Error handling - invalid parameters', async () => {
        const result = await toolManager.executeTool('read-file', {
            // 缺少必需的 path 参数
        });

        assert(!result.success, 'Should fail with invalid parameters');
        assertNotNull(result.error, 'Should have error information');
    });

    // 运行所有测试
    await testFramework.run();

    // 清理
    await toolManager.cleanup();
}

// 运行测试
runTests().catch(error => {
    console.error('Test execution failed:', error);
    process.exit(1);
});
